package com.miaoxie.forum.module.auth.shared.interceptor;

import java.io.BufferedReader;
import java.lang.reflect.Method;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.miaoxie.forum.module.auth.shared.json.JSON;
import com.miaoxie.forum.module.auth.shared.json.JSONPopulator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 
 * Created on 2017-2-8
 * <p>Description: [JSON格式反序列化]</p>
 * @author         苗勰
 * @version
 */
public class JSONInterceptor extends HandlerInterceptorAdapter {
	
private final Log log = LogFactory.getLog(getClass());
	
	/**
	 * 序列化及缓存类
	 */
	private static final ObjectMapper MAPPER = new ObjectMapper();
	private final int temp = 2048;
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
	    throws Exception {
		String contentType = request.getHeader("content-type");
		if (contentType != null) {
			int iSemicolonIdx = contentType.indexOf(';');
			if (iSemicolonIdx != -1) {
				contentType = contentType.substring(0, iSemicolonIdx);
			}
			
			// 如果是多媒体类型直接跳过
			if (contentType.toLowerCase().contains(IProtocol.CONTENT_TYPE_MULTIPART)) {
				return true;
			}
		}
		HandlerMethod handleMethod = (HandlerMethod) handler; 
		Class<?> clazz = handleMethod.getBean().getClass();
		Method method = handleMethod.getMethod();
		//如果在Controll方法上加入JSON的注解，那么就可以在应用这个方法的时候，把错误的结果信息转换为json
	    if (IProtocol.JSON_CONTENT_TYPE.equalsIgnoreCase(contentType) || AnnotationUtils.isAnnotationDeclaredLocally(JSON.class, clazz)
	        	|| (method != null && method.isAnnotationPresent(JSON.class))) {
			BufferedReader reader = request.getReader();
			int bytesRead;
			StringBuilder stringBuilder = new StringBuilder();
			char[] charBuffer = new char[temp];
			if(reader!=null) {
				while ((bytesRead = reader.read(charBuffer)) > 0) {
					stringBuilder.append(charBuffer, 0, bytesRead);
				}
			}
			if (stringBuilder.toString().length() > 0) {
				Map json = MAPPER.readValue(stringBuilder.toString(), Map.class);
				JSONPopulator.populateObject(handleMethod, json);
			}
		} else {
			if (log.isDebugEnabled()) {
				log.debug("Content type must be 'application/json' or 'application/json-rpc'. Ignoring request with content type "
						+ contentType);
			}
		}
		
		return true;
	}
}
